package com.huawang.mdesign.model.service.inter;

import com.huawang.business.command.CommandAddType;
import com.huawang.business.constants.ErrorCode;
import com.huawang.business.constants.ModelConstantURI;
import com.huawang.business.dto.*;
import com.huawang.business.exception.AbortExecutionException;
import com.huawang.business.service.judge.BusinessJudgeService;
import com.huawang.business.service.model.base.ElementNameService;
import com.huawang.business.service.model.base.UmlService;
import com.huawang.business.service.model.core.InternalUmlService;
import com.huawang.business.service.model.core.ModelPropertyInfoService;
import com.huawang.business.service.model.core.add.operation.CreateConnector;
import com.huawang.business.service.transaction.TransactionServiceImpl;
import com.huawang.business.util.InstanceVoUtils;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.cmof.reflection.impl.BasicRElement;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.core.semantics.entity.queryResult.MofResultContainer;
import com.huawang.core.semantics.entity.queryResult.QueryPropertyForm;
import com.huawang.core.semantics.entity.transaction.LocalTransaction;
import com.huawang.core.semantics.exception.LocalTransactionNotStartException;
import com.huawang.core.semantics.exception.TransactionNotExistingException;
import com.huawang.mdesign.model.service.dto.CreateIbdDTO;
import com.huawang.mdesign.model.service.dto.PermutationGroup;
import com.huawang.mdesign.model.service.dto.createibd.*;
import com.huawang.mdesign.model.service.facade.dto.PropertyInfo;
import com.huawang.mdesign.model.service.util.LogUtil;
import com.huawang.mdesign.model.service.vo.ConnectorGroup;
import com.huawang.mdesign.model.service.vo.CreateIbdVo;
import com.huawang.mdesign.model.service.vo.FindOrCreateProxyPortInfo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.huawang.business.constants.ModelActionName.ADD_MODEL;

@Slf4j
@Service
@Primary
public class InternalBlockService {
    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private UmlService umlService;

    @Autowired
    private ModelPropertyInfoService modelPropertyInfoService;

    @Autowired
    private CreateConnector createConnector;

    @Autowired
    private TransactionServiceImpl transactionService;

    @Autowired
    private ElementNameService elementNameService;

    @Autowired
    private BusinessJudgeService businessJudgeService;

    @NotNull
    public List<String> queryPartPropertySwimLane(String projectId, String instanceId) {
        LogUtil.printOnlineLogs("projectId: {}, instanceId: {}", projectId, instanceId);
        final MetaClassInstance block = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(block)) {
            log.error("模型查询失败, 模型id:" + instanceId);
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        MofResultContainer blockContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(
                block,
                Stream.of(UMLDefinitionConstants.Classifier_inheritedMember).collect(Collectors.toList())));
        List<MetaClassInstance> partPropertyList = internalUmlService.getChildren(block, false, projectId).stream()
                .filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.Customization_PartProperty))
                .collect(Collectors.toList());
        final List<MetaClassInstance> inheritPartProperty = blockContainer.queryListInstanceProperty(
                block.getId(), UMLDefinitionConstants.Classifier_inheritedMember).stream()
                .filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.Customization_PartProperty))
                .collect(Collectors.toList());
        List<MetaClassInstance> allPartProperty = Stream.concat(inheritPartProperty.stream(), partPropertyList.stream()).collect(Collectors.toList());
        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId,
                allPartProperty,
                Collections.singletonList(UMLDefinitionConstants.A_represents_activityPartition_activityPartition));
        return modelPropertyInfoMap.values().stream()
                .flatMap(it ->
                        it.queryListInstanceValue(UMLDefinitionConstants.A_represents_activityPartition_activityPartition).stream())
                .map(BasicRElement::getId)
                .collect(Collectors.toList());
    }

    @NotNull
    public CreateIbdVo createIbdBySwimLane(CreateIbdDTO dto) {
        LogUtil.printSerializeOnlineLogs("dto: ", dto);
        final String projectId = dto.getProjectId();
        final MetaClassInstance block = internalUmlService.fetchInstance(dto.getInstanceId(), projectId);
        if (Objects.isNull(block)) {
            log.error("模块模型查询失败");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        CreateIbdVo createIbdVo = new CreateIbdVo();
        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            ModelPropertyInfo blockPropertyInfo = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId, block,
                    Stream.of(UMLDefinitionConstants.NamedElement_name,
                            UMLDefinitionConstants.Classifier_inheritedMember,
                            UMLDefinitionConstants.BehavioredClassifier_ownedBehavior).collect(Collectors.toList()));

            final List<MetaClassInstance> inheritPartPropertyList = blockPropertyInfo.queryListInstanceValue(
                    UMLDefinitionConstants.Classifier_inheritedMember).stream()
                    .filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.Customization_PartProperty))
                    .collect(Collectors.toList());
            List<MetaClassInstance> partPropertyList = internalUmlService.getChildren(block, false, projectId).stream()
                    .filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.Customization_PartProperty))
                    .collect(Collectors.toList());
            List<MetaClassInstance> allPartProperty = Stream.concat(inheritPartPropertyList.stream(), partPropertyList.stream())
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(allPartProperty)) {
                log.info("当前元素下无部件属性");
                throw AbortExecutionException.build(ErrorCode.CREATE_IBD_NO_PART_PROPERTY_ERROR);
            }
            Map<String, ModelPropertyInfo> partPropertyMap = modelPropertyInfoService.createModelPropertyInfoMap(
                    projectId,
                    allPartProperty,
                    Stream.of(UMLDefinitionConstants.A_represents_activityPartition_activityPartition,
                            UMLDefinitionConstants.A_allocatedTo_namedElement_namedElement,
                            UMLDefinitionConstants.TypedElement_type).collect(Collectors.toList()));

            List<MetaClassInstance> nodeList = internalUmlService.fetchInstanceByIds(dto.getNodeList(), projectId);
            MetaClassInstance nearestPackage = umlService.fetchOwningPackage(projectId, block);
            List<ItemFlowGroup> itemFlowGroupList = createItemFlowGroupList(
                    projectId, partPropertyMap, nodeList, blockPropertyInfo, nearestPackage);
            IbdDisplayModel ibdDisplayModel = initConnectorGroupEndsV2(projectId, partPropertyMap, itemFlowGroupList, nearestPackage);
            ibdDisplayModel.initPartPropertyDisplay(inheritPartPropertyList);
            fillGroupConnector(projectId, block.getId(), ibdDisplayModel);
            AddModelDTO ibdDTO = new AddModelDTO();
            ibdDTO.setProjectId(projectId);
            ibdDTO.setParentId(block.getId());
            ibdDTO.setMetaclass(UMLDefinitionConstants.UMLDiagram);
            ibdDTO.setType(0);
            ibdDTO.setInstanceId(ibdDisplayModel.getIbdModel());
            ibdDTO.setApplyStereotypes(Collections.singletonList(UMLDefinitionConstants.SysMLInternalBlockDiagram));
            ibdDTO.setCustomName(blockPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_name));
            MetaClassInstance ibd = umlService.addModel(ibdDTO);
            umlService.updateModel(projectId, ibd.getId(), UMLDefinitionConstants.Diagram_context, block);
            transactionService.commit(projectId);
            InstanceVoUtils.fillModelResultVo(createIbdVo, transaction);
            createIbdVo.setIbdDisplayModel(ibdDisplayModel);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.ADD_MODEL_ERROR, e);
        }
        return createIbdVo;
    }

    @NotNull
    private List<ItemFlowGroup> createItemFlowGroupList(String projectId,
                                                        Map<String, ModelPropertyInfo> partPropertyMap,
                                                        List<MetaClassInstance> nodeList,
                                                        ModelPropertyInfo blockPropertyInfo,
                                                        MetaClassInstance nearestPackage) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, nodeList: {}, nearestPackage: {}", projectId, nodeList,
                nearestPackage);
        // partPropertyMap中部件属性类型一定不为空：如果部件属性的type为空, 则一定不存在通信路径, 直接过滤
        partPropertyMap.values().removeIf(value -> Objects.isNull(value.queryInstanceValue(UMLDefinitionConstants.TypedElement_type)));
        List<MetaClassInstance> swimLaneList = partPropertyMap.values().stream().flatMap(it ->
                it.queryListInstanceValue(UMLDefinitionConstants.A_represents_activityPartition_activityPartition).stream())
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(swimLaneList)) {
            log.info("模块下部件属性均无映射泳道");
            throw AbortExecutionException.build(ErrorCode.CREATE_IBD_NO_COMMUNICATION_ERROR);
        }
        // 批量泳道所在画布全量模型的属性
        List<MetaClassInstance> activityEdgeList = nodeList.stream().filter(it ->
                internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.ActivityEdge)).collect(Collectors.toList());
        List<MetaClassInstance> activityNodeList = nodeList.stream().filter(it ->
                internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.ActivityNode)).collect(Collectors.toList());
        Map<String, Set<String>> givenTypesMap = internalUmlService.getGivenTypes(projectId, nodeList);

        Map<String, ModelPropertyInfo> activityEdgeMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId,
                activityEdgeList,
                Stream.of(UMLDefinitionConstants.ActivityEdge_source,
                        UMLDefinitionConstants.ActivityEdge_target,
                        UMLDefinitionConstants.A_realizingActivityEdge_informationFlow_informationFlow).collect(Collectors.toList()));

        Map<String, ModelPropertyInfo> activityNodeMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId,
                activityNodeList,
                Stream.of(UMLDefinitionConstants.ActivityNode_incoming,
                        UMLDefinitionConstants.ActivityNode_outgoing,
                        UMLDefinitionConstants.Action_input,
                        UMLDefinitionConstants.Action_output,
                        UMLDefinitionConstants.TypedElement_type,
                        UMLDefinitionConstants.NamedElement_allocatedTo).collect(Collectors.toList()));

        Map<String, ModelPropertyInfo> swimLaneMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId,
                swimLaneList,
                Stream.of(UMLDefinitionConstants.ActivityPartition_node, UMLDefinitionConstants.ActivityPartition_represents)
                        .collect(Collectors.toList()));

        List<ItemFlowGroup> itemFlowGroupList = new ArrayList<>();
        itemFlowGroupList.addAll(callBehaviorActionPermutation(projectId, swimLaneMap, partPropertyMap, activityNodeMap));
        itemFlowGroupList.addAll(activityParameterNodePermutation(
                projectId, blockPropertyInfo, swimLaneMap, partPropertyMap, activityNodeMap));

        if (CollectionUtils.isEmpty(itemFlowGroupList.stream().flatMap(it ->
                it.getActionPermutationGroups().stream()).collect(Collectors.toList()))) {
            log.info("无部件属性排列组合 或 部件属性间无动作排列组合");
            throw AbortExecutionException.build(ErrorCode.CREATE_IBD_NO_COMMUNICATION_ERROR);
        }

        List<MetaClassInstance> partPropertyTypeList = itemFlowGroupList.stream().flatMap(it ->
                Stream.of(it.getSourcePartPropertyType(), it.getTargetPartPropertyType()))
                .collect(Collectors.toList());
        Map<String, ModelPropertyInfo> partPropertyTypeMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId,
                partPropertyTypeList,
                Stream.of(UMLDefinitionConstants.A_informationSource_informationFlow_informationFlow,
                        UMLDefinitionConstants.A_informationTarget_informationFlow_informationFlow).collect(Collectors.toList()));
        itemFlowGroupList.forEach(itemFlowGroup -> {
            MetaClassInstance sourcePartPropertyType = itemFlowGroup.getSourcePartPropertyType();
            MetaClassInstance targetPartPropertyType = itemFlowGroup.getTargetPartPropertyType();
            List<ActionPermutationGroup> actionPermutationGroups = itemFlowGroup.getActionPermutationGroups();
            actionPermutationGroups.forEach(actionPermutationGroup -> {
                MetaClassInstance firstNode = actionPermutationGroup.getFirstNode();
                MetaClassInstance secondNode = actionPermutationGroup.getSecondNode();
                Set<List<MetaClassInstance>> routesSet = findRouteBetweenAction(projectId, activityEdgeMap, activityNodeMap, firstNode, secondNode);
                List<MetaClassInstance> commonItemFlow = routesSet.stream().flatMap(routes ->
                        queryCommonItemFlow(routes, activityEdgeMap).stream()).collect(Collectors.toList());
                actionPermutationGroup.setRoutes(routesSet);
                actionPermutationGroup.setItemFlowBGroup(commonItemFlow);
            });
            itemFlowGroup.appendPinConveyedPermutation(givenTypesMap, activityEdgeMap, activityNodeMap);
            itemFlowGroup.initBiDirectionItemFlow(projectId, partPropertyTypeMap, sourcePartPropertyType, targetPartPropertyType, businessJudgeService);
        });
        // 填充ConveyedPermutationGroup属性
        fillConveyedPermutationGroup(projectId, itemFlowGroupList);
        fillNewItemFlow(projectId, itemFlowGroupList, nearestPackage);
        return itemFlowGroupList;
    }

    /**
     * desciption:查询实现了所有路径的项流
     */
    @NotNull
    private static List<MetaClassInstance> queryCommonItemFlow(List<MetaClassInstance> routes,
                                                               Map<String, ModelPropertyInfo> activityEdgeMap) {
        LogUtil.printSerializeOnlineLogs("routes: ", routes);
        return routes.stream()
                .map(route -> (List<MetaClassInstance>) new ArrayList<>(activityEdgeMap.get(route.getId())
                        .queryListInstanceValue(UMLDefinitionConstants.A_realizingActivityEdge_informationFlow_informationFlow))).reduce((list1, list2) -> {
                    list1.retainAll(list2);
                    return list1;
                }).orElse(Collections.emptyList());
    }

    private void fillConveyedPermutationGroup(String projectId, List<ItemFlowGroup> itemFlowGroupList) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, itemFlowGroupList: {}", projectId, itemFlowGroupList);
        List<MetaClassInstance> allItemFLow = internalUmlService.querySpecifiedInstanceList(projectId, UMLDefinitionConstants.SysML_ItemFlow);
        MofResultContainer itemFlowContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(
                allItemFLow,
                Stream.of(UMLDefinitionConstants.InformationFlow_informationSource,
                        UMLDefinitionConstants.InformationFlow_informationTarget,
                        UMLDefinitionConstants.InformationFlow_conveyed).collect(Collectors.toList())));
        // 填充对象流/活动参数节点的传递项排列组合
        for (int i = 0; i < itemFlowGroupList.size(); i++) {
            ItemFlowGroup itemFlowGroup = itemFlowGroupList.get(i);
            Set<MetaClassInstance> sourceAllRepresentTypes = itemFlowGroup.getSourceAllRepresentType();
            Set<MetaClassInstance> targetAllRepresentTypes = itemFlowGroup.getTargetAllRepresentType();
            ItemFlowGroup reverseItemFlowGroup = (i % 2 == 0) ? itemFlowGroupList.get(i + 1) : itemFlowGroupList.get(i - 1);
            List<ActionPermutationGroup> actionPermutationGroups = itemFlowGroup.getActionPermutationGroups();
            Set<MetaClassInstance> commonItemFlow = actionPermutationGroups.stream().flatMap(it -> it.getItemFlowBGroup().stream()).collect(Collectors.toSet());
            Set<MetaClassInstance> forwardConveyed = commonItemFlow.stream()
                    .filter(it -> {
                        MetaClassInstance source = itemFlowContainer.queryListInstanceProperty(
                                it.getId(), UMLDefinitionConstants.InformationFlow_informationSource).get(0);
                        MetaClassInstance target = itemFlowContainer.queryListInstanceProperty(
                                it.getId(), UMLDefinitionConstants.InformationFlow_informationTarget).get(0);
                        return fetchGeneralAndAggregation(projectId, sourceAllRepresentTypes).contains(source.getId()) &&
                                fetchGeneralAndAggregation(projectId, targetAllRepresentTypes).contains(target.getId());
                    })
                    .flatMap(it -> itemFlowContainer.queryListInstanceProperty(it.getId(), UMLDefinitionConstants.InformationFlow_conveyed).stream())
                    .collect(Collectors.toSet());
            Set<MetaClassInstance> reverseConveyed = commonItemFlow.stream()
                    .filter(it -> {
                        MetaClassInstance source = itemFlowContainer.queryListInstanceProperty(
                                it.getId(), UMLDefinitionConstants.InformationFlow_informationSource).get(0);
                        MetaClassInstance target = itemFlowContainer.queryListInstanceProperty(
                                it.getId(), UMLDefinitionConstants.InformationFlow_informationTarget).get(0);
                        return !fetchGeneralAndAggregation(projectId, sourceAllRepresentTypes).contains(source.getId()) ||
                                !fetchGeneralAndAggregation(projectId, targetAllRepresentTypes).contains(target.getId());
                    })
                    .flatMap(it -> itemFlowContainer.queryListInstanceProperty(it.getId(), UMLDefinitionConstants.InformationFlow_conveyed).stream())
                    .collect(Collectors.toSet());
            itemFlowGroup.appendConveyed(forwardConveyed);
            reverseItemFlowGroup.appendConveyed(reverseConveyed);
        }
        for (int i = 0; i < itemFlowGroupList.size(); i++) {
            ItemFlowGroup itemFlowGroup = itemFlowGroupList.get(i);
            Map<MetaClassInstance, String> endsLimitedDirectionMap = itemFlowGroup.getEndsLimitedDirectionMap();
            ItemFlowGroup reverseItemFlowGroup = (i % 2 == 0) ? itemFlowGroupList.get(i + 1) : itemFlowGroupList.get(i - 1);
            if (i % 2 == 0) {
                Set<MetaClassInstance> forwardConveyed = itemFlowGroup.getConveyed();
                Set<MetaClassInstance> reverseConveyed = reverseItemFlowGroup.getConveyed();
                Set<MetaClassInstance> intersectionConveyed = new HashSet<>(forwardConveyed);
                intersectionConveyed.retainAll(reverseConveyed);
                List<ConveyedPermutationGroup> biDirectionConveyedPermutation = intersectionConveyed.stream().map(it ->
                        createConveyedPermutationGroup(it, it, true, null)).collect(Collectors.toList());
                itemFlowGroup.getConveyedPermutationGroups().addAll(biDirectionConveyedPermutation);
                forwardConveyed.removeAll(intersectionConveyed);
                reverseConveyed.removeAll(intersectionConveyed);
            }
            List<ConveyedPermutationGroup> conveyedPermutationGroups = itemFlowGroup.getConveyed().stream().map(it ->
            {
                String endsLimitedDirection = endsLimitedDirectionMap.getOrDefault(it, null);
                return createConveyedPermutationGroup(it, it, false, endsLimitedDirection);
            }).collect(Collectors.toList());
            itemFlowGroup.getConveyedPermutationGroups().addAll(conveyedPermutationGroups);
        }
    }

    @NotNull
    private Set<String> fetchGeneralAndAggregation(String projectId, @NotNull Set<MetaClassInstance> instances) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instances: {}", projectId, instances);
        // 泛化链存在内存中，但聚合链没存在内存中，这里性能很差
        final Map<String, Set<MetaClassInstance>> aggregationReverseCascades = new HashMap<>();
        internalUmlService.findAggregationReverseCascades(projectId, new ArrayList<>(instances), new HashSet<>(),
                aggregationReverseCascades);
        final List<String> generalsCascade = internalUmlService.findGeneralsIdsCascade(projectId,
                instances.stream().map(BasicRElement::getId).collect(Collectors.toList()), true);
        final List<String> aggregations = aggregationReverseCascades.values().stream()
                .flatMap(Collection::stream).map(BasicRElement::getId).collect(Collectors.toList());
        generalsCascade.addAll(aggregations);
        return new HashSet<>(generalsCascade);
    }

    @NotNull
    private static ConveyedPermutationGroup createConveyedPermutationGroup(MetaClassInstance firstNode,
                                                                           MetaClassInstance secondNode,
                                                                           Boolean isBiDirectionTransmit,
                                                                           String endsLimitedDirection) {
        LogUtil.printSerializeOnlineLogs("firstNode: {}, secondNode: {}, isBiDirectionTransmit: {}, endsLimitedDirection: {}",
                firstNode, secondNode, isBiDirectionTransmit, endsLimitedDirection);
        ConveyedPermutationGroup conveyedPermutationGroup = new ConveyedPermutationGroup();
        conveyedPermutationGroup.setFirstNode(firstNode);
        conveyedPermutationGroup.setSecondNode(secondNode);
        conveyedPermutationGroup.setIsBiDirectionTransmit(isBiDirectionTransmit);
        conveyedPermutationGroup.setEndsLimitedDirection(endsLimitedDirection);
        return conveyedPermutationGroup;
    }

    /**
     * desciption:计算不同泳道间调用行为动作的所有排列组合：1.排列组合部件属性 2.排列组合部件属性下所有泳道的节点
     */
    @NotNull
    private List<ItemFlowGroup> callBehaviorActionPermutation(@NotNull String projectId,
                                                              @NotNull Map<String, ModelPropertyInfo> swimLaneMap,
                                                              @NotNull Map<String, ModelPropertyInfo> partPropertyMap,
                                                              @NotNull Map<String, ModelPropertyInfo> activityNodeMap) {
        LogUtil.printOnlineLogs("callBehaviorActionPermutation -> projectId: ", projectId);
        List<ModelPropertyInfo> partPropertyInfoList = new ArrayList<>(partPropertyMap.values());
        List<PermutationGroup> partPropertyPermutationList = new ArrayList<>();
        // 计算不同部件属性间所在泳道的所有排列组合(firstNode与secondNode相等的不算在内)
        for (int i = 0; i < partPropertyInfoList.size(); i++) {
            for (int j = i + 1; j < partPropertyInfoList.size(); j++) {
                MetaClassInstance firstPartProperty = partPropertyInfoList.get(i).getInstance();
                MetaClassInstance secondPartProperty = partPropertyInfoList.get(j).getInstance();
                PermutationGroup partPropertyPermutation = new PermutationGroup();
                partPropertyPermutation.setFirstNode(firstPartProperty);
                partPropertyPermutation.setSecondNode(secondPartProperty);
                PermutationGroup reversePartPropertyPermutation = new PermutationGroup();
                reversePartPropertyPermutation.setFirstNode(secondPartProperty);
                reversePartPropertyPermutation.setSecondNode(firstPartProperty);
                partPropertyPermutationList.addAll(Stream.of(partPropertyPermutation, reversePartPropertyPermutation)
                        .collect(Collectors.toList()));
            }
        }

        return partPropertyPermutationList.stream().map(it -> {
            MetaClassInstance firstPartProperty = it.getFirstNode();
            MetaClassInstance secondPartProperty = it.getSecondNode();
            ModelPropertyInfo firstPartPropertyInfo = partPropertyMap.get(firstPartProperty.getId());
            ModelPropertyInfo secondPartPropertyInfo = partPropertyMap.get(secondPartProperty.getId());
            MetaClassInstance firstType = firstPartPropertyInfo.queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
            MetaClassInstance secondType = secondPartPropertyInfo.queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
            Set<MetaClassInstance> firstContainNode = queryPartPropertyContainNode(projectId, firstPartPropertyInfo, swimLaneMap);
            Set<MetaClassInstance> secondContainNode = queryPartPropertyContainNode(projectId, secondPartPropertyInfo, swimLaneMap);
            Set<MetaClassInstance> firstAllRepresentType = queryNodeAllRepresentType(
                    projectId, firstContainNode, partPropertyMap, activityNodeMap);
            Set<MetaClassInstance> secondAllRepresentType = queryNodeAllRepresentType(
                    projectId, secondContainNode, partPropertyMap, activityNodeMap);
            ItemFlowGroup itemFlowGroup = new ItemFlowGroup(
                    firstPartProperty.getId(), firstType, firstAllRepresentType,
                    secondPartProperty.getId(), secondType, secondAllRepresentType);
            itemFlowGroup.initActionPermutationGroups(firstContainNode, secondContainNode);
            return itemFlowGroup;
        }).collect(Collectors.toList());
    }

    /**
     * desciption:查询分区内节点所有的泳道代表(部件属性)的类型
     */
    @NotNull
    private Set<MetaClassInstance> queryNodeAllRepresentType(String projectId,
                                                             Set<MetaClassInstance> containNodeSet,
                                                             Map<String, ModelPropertyInfo> partPropertyMap,
                                                             Map<String, ModelPropertyInfo> activityNodeMap) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, containNodeSet: {}", projectId, containNodeSet);
        if (CollectionUtils.isEmpty(containNodeSet)) {
            return Collections.emptySet();
        }
        // 在一个泳道分区下的所有节点其泳道代表肯定一致, 所有只需取一个计算即可
        MetaClassInstance node = containNodeSet.iterator().next();
        List<MetaClassInstance> allRepresent = activityNodeMap.get(node.getId()).queryListInstanceValue(
                UMLDefinitionConstants.NamedElement_allocatedTo)
                .stream()
                .filter(it ->
                        internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.Customization_PartProperty))
                .collect(Collectors.toList());
        return allRepresent.stream().map(it -> {
            ModelPropertyInfo partPropertyInfo = partPropertyMap.get(it.getId());
            // partPropertyMap里面只有选中模块自身或继承得来的部件属性, 这里通过分配关系查询出来的属性可能map里面没值
            return Objects.isNull(partPropertyInfo) ?
                    null : partPropertyInfo.queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
        }).filter(Objects::nonNull).collect(Collectors.toSet());
    }

    @NotNull
    private List<ItemFlowGroup> activityParameterNodePermutation(String projectId,
                                                                 ModelPropertyInfo blockPropertyInfo,
                                                                 Map<String, ModelPropertyInfo> swimLaneMap,
                                                                 Map<String, ModelPropertyInfo> partPropertyMap,
                                                                 Map<String, ModelPropertyInfo> activityNodeMap) {
        LogUtil.printOnlineLogs("activityParameterNodePermutation -> projectId: ", projectId);
        List<ModelPropertyInfo> partPropertyInfoList = new ArrayList<>(partPropertyMap.values());
        // 生成IBD的block其父类下活动参数节点也要参与计算
        List<MetaClassInstance> blockGeneralsCascade = internalUmlService.findGeneralsCascade(
                projectId, blockPropertyInfo.getInstanceId(), true);
        Map<String, ModelPropertyInfo> blockGeneralsCascadeMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId, blockGeneralsCascade, Collections.singletonList(UMLDefinitionConstants.BehavioredClassifier_ownedBehavior));

        List<MetaClassInstance> activityList = blockGeneralsCascadeMap.values().stream()
                .flatMap(it -> it.queryListInstanceValue(UMLDefinitionConstants.BehavioredClassifier_ownedBehavior).stream())
                .filter(it -> isValidActivity(projectId, it, swimLaneMap.keySet()))
                .collect(Collectors.toList());

        List<MetaClassInstance> activityParameterNodes = activityList.stream().flatMap(activity ->
                internalUmlService.getChildren(activity, false, projectId).stream())
                .filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.ActivityParameterNode))
                .collect(Collectors.toList());

        Map<MetaClassInstance, List<MetaClassInstance>> nodeAncestorMap = internalUmlService.getAncestor(
                projectId, activityParameterNodes);

        List<PermutationGroup> permutationList = new ArrayList<>();
        // 第一次排列为 部件属性 -> 活动参数节点
        for (ModelPropertyInfo modelPropertyInfo : partPropertyInfoList) {
            for (MetaClassInstance parameterNode : activityParameterNodes) {
                MetaClassInstance partProperty = modelPropertyInfo.getInstance();
                PermutationGroup permutationGroup = new PermutationGroup();
                permutationGroup.setFirstNode(partProperty);
                permutationGroup.setSecondNode(parameterNode);
                permutationList.add(permutationGroup);
            }
        }
        return permutationList.stream().flatMap(it -> {
            MetaClassInstance partProperty = it.getFirstNode();
            MetaClassInstance activityParameterNode = it.getSecondNode();

            ModelPropertyInfo partPropertyInfo = partPropertyMap.get(partProperty.getId());
            // 查询排列组合两端type
            MetaClassInstance partPropertyType = partPropertyInfo.queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
            MetaClassInstance nodeType = nodeAncestorMap.get(activityParameterNode).stream().filter(ancestor ->
                    internalUmlService.checkInstanceType(projectId, ancestor, UMLDefinitionConstants.SysML_Block))
                    .findFirst().orElse(null);
            Set<MetaClassInstance> containNode = queryPartPropertyContainNode(projectId, partPropertyInfo, swimLaneMap);
            Set<MetaClassInstance> allRepresentType = queryNodeAllRepresentType(
                    projectId, containNode, partPropertyMap, activityNodeMap);

            ItemFlowGroup itemFlowGroup = new ItemFlowGroup(
                    partProperty.getId(), partPropertyType, allRepresentType,
                    null, nodeType, Collections.singleton(nodeType));
            ItemFlowGroup reverseItemFlowGroup = new ItemFlowGroup(
                    null, nodeType, Collections.singleton(nodeType),
                    partProperty.getId(), partPropertyType, allRepresentType);
            itemFlowGroup.initActionPermutationGroups(containNode, Collections.singleton(activityParameterNode));
            reverseItemFlowGroup.initActionPermutationGroups(Collections.singleton(activityParameterNode), containNode);
            return Stream.of(itemFlowGroup, reverseItemFlowGroup);
        }).collect(Collectors.toList());
    }

    /**
     * desciption:查询部件下代表的所有泳道内的节点,并移除掉不存在分配关系的节点
     */
    @NotNull
    private Set<MetaClassInstance> queryPartPropertyContainNode(String projectId,
                                                                ModelPropertyInfo partPropertyInfo,
                                                                Map<String, ModelPropertyInfo> swimLaneMap) {
        LogUtil.printOnlineLogs("queryPartPropertyContainNode -> projectId: ", projectId);
        List<MetaClassInstance> swimLanes = partPropertyInfo.queryListInstanceValue(
                UMLDefinitionConstants.A_represents_activityPartition_activityPartition);
        Set<MetaClassInstance> containNodes = swimLanes.stream().flatMap(it -> {
            ModelPropertyInfo swimLaneInfo = swimLaneMap.get(it.getId());
            return swimLaneInfo.queryListInstanceValue(UMLDefinitionConstants.ActivityPartition_node)
                    .stream().filter(node -> internalUmlService.checkInstanceType(projectId, node, UMLDefinitionConstants.Action));
        }).collect(Collectors.toSet());
        containNodes.retainAll(partPropertyInfo.queryListInstanceValue(
                UMLDefinitionConstants.A_allocatedTo_namedElement_namedElement));
        return containNodes;
    }


    /**
     * desciption:过滤出子节点包含泳道的活动，该类活动才需要获取活动参数节点进行计算
     *
     * @param projectId:项目id
     * @param instance:待生成模块下的行为
     * @param swimLaneIdList：模块下部件属性被分配的所有泳道
     * @return java.lang.Boolean
     * @author lx
     * @date 2024/1/26
     */
    @NotNull
    private Boolean isValidActivity(String projectId, MetaClassInstance instance, Set<String> swimLaneIdList) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instance: {}, swimLaneIdList: {}", projectId, instance,
                swimLaneIdList);
        if (!internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Activity)) {
            return false;
        }
        // 如果活动子节点与泳道节点不存在交集,则无需计算下面的活动参数节点
        List<String> childrenIdList = internalUmlService.getChildren(instance, false, projectId)
                .stream().map(BasicRElement::getId).collect(Collectors.toList());
        return !Collections.disjoint(childrenIdList, swimLaneIdList);
    }

    /**
     * desciption:查询行为间的活动路径
     */
    @NotNull
    private Set<List<MetaClassInstance>> findRouteBetweenAction(@NotNull String projectId,
                                                                @NotNull Map<String, ModelPropertyInfo> activityEdgeMap,
                                                                @NotNull Map<String, ModelPropertyInfo> activityNodeMap,
                                                                @NotNull MetaClassInstance startAction,
                                                                @NotNull MetaClassInstance endAction) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, startAction: {}, endAction: {}", projectId, startAction,
                endAction);
        Set<List<MetaClassInstance>> routesSet = new HashSet<>();
        // 活动参数节点也可以作为查找路径两端，但如果两端均为活动参数节点，则视作无物质传递路径
        if (internalUmlService.checkInstanceType(projectId, startAction, UMLDefinitionConstants.ActivityParameterNode)
                && internalUmlService.checkInstanceType(projectId, endAction, UMLDefinitionConstants.ActivityParameterNode)) {
            return routesSet;
        }
        if (Objects.isNull(activityNodeMap.get(endAction.getId()))) {
            log.error("模型{}无需参与生成ibd图的计算", endAction.getId());
            throw AbortExecutionException.build(ErrorCode.QUERY_MODEL_ERROR);
        }
        Map<MetaClassInstance, List<ActivityEdgeRoute>> activityEdgeRoutesMap = new HashMap<>();
        List<MetaClassInstance> visitList = new ArrayList<>();
        List<MetaClassInstance> endList = new ArrayList<>();
        visitList.add(startAction);
        visitList.addAll(activityNodeMap.get(startAction.getId()).queryListInstanceValue(UMLDefinitionConstants.Action_output));
        // 初始化访问路径
        visitList.forEach(it -> {
            ActivityEdgeRoute activityEdgeRoute = new ActivityEdgeRoute();
            activityEdgeRoute.setInstanceLastNode(it);
            activityEdgeRoute.setInstanceRoutes(new ArrayList<>());
            activityEdgeRoutesMap.put(it, Collections.singletonList(activityEdgeRoute));
        });
        endList.add(endAction);
        endList.addAll(activityNodeMap.get(endAction.getId()).queryListInstanceValue(UMLDefinitionConstants.Action_input));
        while (CollectionUtils.isNotEmpty(visitList)) {
            // 查询连接边，temp存放该节点下一连接边信息
            MetaClassInstance node = visitList.get(0);
            ModelPropertyInfo activityNodeInfo = activityNodeMap.get(node.getId());
            List<MetaClassInstance> tempEdgeList = activityNodeInfo.queryListInstanceValue(UMLDefinitionConstants.ActivityNode_outgoing);
            // 如果没有连接边，走到死路，直接remove掉末节点为node的所有路径
            if (CollectionUtils.isNotEmpty(tempEdgeList)) {
                // 存在连接边，获取连接边末节点为node的所有路径
                List<ActivityEdgeRoute> routes = activityEdgeRoutesMap.get(node);

                tempEdgeList.forEach(tempEdge -> {
                    MetaClassInstance nextNode = activityEdgeMap.get(tempEdge.getId()).queryInstanceValue(UMLDefinitionConstants.ActivityEdge_target);
                    if (Objects.isNull(nextNode)) {
                        return;
                    }
                    List<ActivityEdgeRoute> newRoutes = new ArrayList<>(routes.size());
                    routes.forEach(activityEdgeRoute -> {
                        ActivityEdgeRoute newRoute = new ActivityEdgeRoute();
                        List<MetaClassInstance> instanceRoutes = new ArrayList<>(activityEdgeRoute.getInstanceRoutes());
                        instanceRoutes.add(tempEdge);
                        newRoute.setInstanceRoutes(instanceRoutes);
                        newRoute.setInstanceLastNode(nextNode);
                        newRoutes.add(newRoute);
                    });
                    Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, nextNode);
                    if (endList.contains(nextNode)) {
                        routesSet.addAll(newRoutes.stream().map(ActivityEdgeRoute::getInstanceRoutes).collect(Collectors.toSet()));
                    } else if (!givenTypes.contains(UMLDefinitionConstants.Pin) &&
                            !givenTypes.contains(UMLDefinitionConstants.CallBehaviorAction) &&
                            !givenTypes.contains(UMLDefinitionConstants.ActivityParameterNode)) {
                        visitList.add(nextNode);
                        activityEdgeRoutesMap.put(nextNode, newRoutes);
                    } else {
                        log.info("nextNode不在目标节点中，同时该节点类型为Pin、CallBehaviorAction或ActivityParameterNode，不再继续查找路径");
                    }
                });
            }
            activityEdgeRoutesMap.remove(node);
            visitList.remove(node);
        }
        return routesSet;
    }

    private void fillNewItemFlow(String projectId,
                                 List<ItemFlowGroup> itemFlowGroupList,
                                 MetaClassInstance nearestPackage) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, itemFlowGroupList: {}, nearestPackage: {}", projectId,
                itemFlowGroupList, nearestPackage);
        Map<String, ModelPropertyInfo> itemFlowInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId,
                itemFlowGroupList.stream().flatMap(it -> {
                    List<MetaClassInstance> itemFlowBGroup = it.getActionPermutationGroups().stream().flatMap(actionPermutation ->
                            actionPermutation.getItemFlowBGroup().stream()).collect(Collectors.toList());
                    Set<MetaClassInstance> intersectionItemFlow = it.getIntersectionItemFlow();
                    return Stream.of(itemFlowBGroup, intersectionItemFlow).flatMap(Collection::stream);
                }).collect(Collectors.toList()),
                Stream.of(UMLDefinitionConstants.InformationFlow_informationSource,
                        UMLDefinitionConstants.InformationFlow_informationTarget,
                        UMLDefinitionConstants.InformationFlow_conveyed).collect(Collectors.toList()));

        MofResultContainer conveyedContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(
                itemFlowInfoMap.values().stream().flatMap(it -> it.queryListInstanceValue(UMLDefinitionConstants.InformationFlow_conveyed).stream())
                        .collect(Collectors.toList()),
                Collections.singletonList(UMLDefinitionConstants.NamedElement_name)));

        List<AddModelDTO> addModelDTOS = new ArrayList<>();
        List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();

        itemFlowGroupList.forEach(itemFlowGroup -> {
            MetaClassInstance sourceType = itemFlowGroup.getSourcePartPropertyType();
            MetaClassInstance targetType = itemFlowGroup.getTargetPartPropertyType();

            Set<MetaClassInstance> intersectionItemFlow = itemFlowGroup.getIntersectionItemFlow();
            Set<MetaClassInstance> itemFlowConveyed = itemFlowGroup.getConveyed();
            Map<MetaClassInstance, Set<Object>> needCreateItemFlowMap = itemFlowGroup.getNeedCreateItemFlowMap();
            // 如果两端项流传递项存在差集,则需要新建项流，并将差集传递项设置为项流的传递项属性
            Set<MetaClassInstance> conveyedListB = intersectionItemFlow.stream().flatMap(itemFlow ->
                    itemFlowInfoMap.get(itemFlow.getId()).queryListInstanceValue(UMLDefinitionConstants.InformationFlow_conveyed).stream()).collect(Collectors.toSet());
            itemFlowConveyed.removeAll(conveyedListB);
            itemFlowConveyed.forEach(conveyed -> {
                if (!needCreateItemFlowMap.get(conveyed).contains(true)) {
                    log.info("对象流栓之间传递对象{}不需要创建项流", conveyed.getId());
                    return;
                }
                final String initItemFlowId = ModelConstantURI.initInstanceId();
                final String conveyedName = conveyedContainer.queryStringProperty(conveyed.getId(), UMLDefinitionConstants.NamedElement_name);
                final String defaultName = Objects.isNull(conveyedName) ? null : "流" + conveyedName;
                AddModelDTO addModelDTO = new AddModelDTO();
                addModelDTO.setProjectId(projectId);
                addModelDTO.setType(1);
                addModelDTO.setMetaclass(UMLDefinitionConstants.InformationFlow);
                addModelDTO.setDefaultName(defaultName);
                addModelDTO.setSource(sourceType.getId());
                addModelDTO.setTarget(targetType.getId());
                addModelDTO.setParentId(nearestPackage.getId());
                addModelDTO.setApplyStereotypes(Collections.singletonList(UMLDefinitionConstants.SysML_ItemFlow));
                addModelDTO.setInstanceId(initItemFlowId);

                addModelDTOS.add(addModelDTO);
                updateModelDTOS.add(new UpdateModelDTO(
                        projectId, initItemFlowId, UMLDefinitionConstants.InformationFlow_conveyed, Collections.singletonList(conveyed)));
                itemFlowGroup.getNewItemFlow().add(initItemFlowId);
            });

        });

        if (CollectionUtils.isNotEmpty(addModelDTOS)) {
            umlService.addModel(addModelDTOS);
        }
        if (CollectionUtils.isNotEmpty(updateModelDTOS)) {
            umlService.updateModelByBatch(updateModelDTOS);
        }
    }

    @NotNull
    private IbdDisplayModel initConnectorGroupEndsV2(String projectId,
                                                     Map<String, ModelPropertyInfo> partPropertyMap,
                                                     List<ItemFlowGroup> itemFlowGroupList,
                                                     MetaClassInstance nearestPackage) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, itemFlowGroupList: {}, nearestPackage: {}", projectId,
                itemFlowGroupList, nearestPackage);
        // 用InterfaceBlockInfo保存接口模块的所有信息:包括新增的接口模块和代理端口信息
        List<InterfaceBlockInfo> interfaceBlockInfos = initInterfaceBlockInfo(projectId);
        createAndFillInterfaceBlockInfo(projectId, interfaceBlockInfos, itemFlowGroupList, nearestPackage);
        MofResultContainer itemFlowContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(
                itemFlowGroupList.stream().flatMap(it ->
                        Stream.concat(
                                Stream.concat(it.getIntersectionItemFlow().stream(), it.getReverseIntersectionItemFlow().stream()),
                                internalUmlService.fetchInstanceByIds(new ArrayList<>(it.getNewItemFlow()), projectId).stream()))
                        .collect(Collectors.toList()),
                Stream.of(UMLDefinitionConstants.InformationFlow_conveyed).collect(Collectors.toList())));

        List<AddModelDTO> addProxyPortDTOS = new ArrayList<>();
        List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
        IbdDisplayModel ibdDisplayModel = new IbdDisplayModel();
        ibdDisplayModel.initPartPropertyGroup(projectId, partPropertyMap);
        itemFlowGroupList.forEach(it -> it.fillIbdId(ibdDisplayModel.getIbdModel()));

        Map<String, MetaClassInstance> interfaceBlockInstanceMap = internalUmlService.fetchInstances(
                interfaceBlockInfos.stream().map(InterfaceBlockInfo::getInterfaceBlockId).collect(Collectors.toList()), projectId);

        itemFlowGroupList.forEach(itemFlowGroup -> {
            MetaClassInstance sourcePartPropertyType = itemFlowGroup.getSourcePartPropertyType();
            MetaClassInstance targetPartPropertyType = itemFlowGroup.getTargetPartPropertyType();

            itemFlowGroup.getConveyedPermutationGroups().forEach(conveyedPermutationGroup -> {
                Boolean isBiDirectionTransmit = conveyedPermutationGroup.getIsBiDirectionTransmit();
                FindOrCreateProxyPortInfo sourceFind = new FindOrCreateProxyPortInfo(projectId, interfaceBlockInfos,
                        conveyedPermutationGroup,
                        sourcePartPropertyType, interfaceBlockInstanceMap, true, addProxyPortDTOS, updateModelDTOS);
                InterfaceBlockInfo sourceSatisfiedInfo = findOrCreateProxyPort(sourceFind);
                FindOrCreateProxyPortInfo targetFind = new FindOrCreateProxyPortInfo(projectId, interfaceBlockInfos,
                        conveyedPermutationGroup,
                        targetPartPropertyType, interfaceBlockInstanceMap, false, addProxyPortDTOS, updateModelDTOS);
                InterfaceBlockInfo targetSatisfiedInfo = findOrCreateProxyPort(targetFind);
                // 将新建的代理端口信息存储至interfaceBlockInfos的ProxyPortList
                Set<MetaClassInstance> sourceGeneralsCascade = Objects.nonNull(sourceSatisfiedInfo) ?
                        sourceSatisfiedInfo.getAlreadyConveyedSet().stream().flatMap(it ->
                                internalUmlService.findGeneralsCascade(projectId, it.getId(), true).stream())
                                .collect(Collectors.toSet()) : new HashSet<>();
                ibdDisplayModel.fillDisplayGroup(sourceSatisfiedInfo, targetSatisfiedInfo, sourceGeneralsCascade,
                        itemFlowContainer, itemFlowGroup, isBiDirectionTransmit);
            });
        });


        if (CollectionUtils.isNotEmpty(addProxyPortDTOS)) {
            umlService.addModel(addProxyPortDTOS);
        }
        if (CollectionUtils.isNotEmpty(updateModelDTOS)) {
            umlService.updateModelByBatch(updateModelDTOS);
        }
        // 代理端口为空的部件属性不展示
        ibdDisplayModel.filterEmptyPartProperty();
        return ibdDisplayModel;
    }

    @NotNull
    private static Set<String> calculateLimitedDirection(Boolean isBiDirectionTransmit,
                                                         Boolean isCalculateSource,
                                                         String endsLimitedDirection) {
        LogUtil.printOnlineLogs("isBiDirectionTransmit: {}, isCalculateSource: {}, endsLimitedDirection: {}",
                isBiDirectionTransmit, isCalculateSource, endsLimitedDirection);
        Set<String> limitedDirectionSet = new HashSet<>();
        limitedDirectionSet.add(UMLDefinitionConstants.SysML_FlowDirectionKind_inout);
        // 如果为双向传输，则两端必须为inout，直接返回
        if (BooleanUtils.isTrue(isBiDirectionTransmit)) {
            return limitedDirectionSet;
        }
        // 如果两端方向已经限制，则直接返回
        if (Objects.nonNull(endsLimitedDirection)) {
            limitedDirectionSet.add(endsLimitedDirection);
            return limitedDirectionSet;
        }
        if (BooleanUtils.isTrue(isCalculateSource)) {
            limitedDirectionSet.add(UMLDefinitionConstants.SysML_FlowDirectionKind_out);
        } else {
            limitedDirectionSet.add(UMLDefinitionConstants.SysML_FlowDirectionKind_in);
        }
        return limitedDirectionSet;
    }

    @Nullable
    private static InterfaceBlockInfo querySatisfiedInterfaceBlock(List<InterfaceBlockInfo> interfaceBlockInfos,
                                                                   MetaClassInstance conveyed,
                                                                   Set<String> limitedDirectionSet) {
        LogUtil.printSerializeOnlineLogs("interfaceBlockInfos: {}, conveyed: {}, limitedDirectionSet: {}",
                interfaceBlockInfos, conveyed, limitedDirectionSet);
        // 如果物质必须inout双向传输，则接口模块下的流属性必须为inout才算匹配;如果不为inout传输,则只需要接口模块可以传递该物质即可
        Boolean isFetchPropertyDirection = limitedDirectionSet.size() == 1
                && limitedDirectionSet.contains(UMLDefinitionConstants.SysML_FlowDirectionKind_inout);
        return BooleanUtils.isTrue(isFetchPropertyDirection) ?
                interfaceBlockInfos.stream().filter(it ->
                        Objects.nonNull(it.querySatisfiedPropertyInfo(conveyed, limitedDirectionSet)))
                        .findFirst().orElse(null) :
                interfaceBlockInfos.stream().filter(it -> it.getCanConveyedSet().contains(conveyed)).findFirst().orElse(null);
    }

    @Nullable
    private static InterfaceBlockInfo querySatisfiedInterfaceBlock(List<InterfaceBlockInfo> interfaceBlockInfos,
                                                                   MetaClassInstance conveyed,
                                                                   List<MetaClassInstance> typeGeneralsCascade,
                                                                   Set<String> limitedDirectionSet) {
        LogUtil.printSerializeOnlineLogs("interfaceBlockInfos: {}, conveyed: {}, typeGeneralsCascade: {}, limitedDirectionSet {}:",
                interfaceBlockInfos, conveyed, typeGeneralsCascade, limitedDirectionSet);
        // 如果物质必须inout双向传输，则接口模块下的流属性必须为inout才算匹配;如果不为inout传输,则只需要代理端口方向匹配即可
        Boolean isFetchPropertyDirection = limitedDirectionSet.size() == 1
                && limitedDirectionSet.contains(UMLDefinitionConstants.SysML_FlowDirectionKind_inout);
        return BooleanUtils.isTrue(isFetchPropertyDirection) ?
                interfaceBlockInfos.stream().filter(it ->
                        Objects.nonNull(it.querySatisfiedPropertyInfo(conveyed, limitedDirectionSet)) &&
                                Objects.nonNull(it.querySatisfiedProxyPortInfo(typeGeneralsCascade, Collections.emptySet())))
                        .findFirst().orElse(null) :
                interfaceBlockInfos.stream().filter(it ->
                        Objects.nonNull(it.querySatisfiedProxyPortInfo(typeGeneralsCascade, limitedDirectionSet)) &&
                                it.getCanConveyedSet().contains(conveyed))
                        .findFirst().orElse(null);
    }

    @Nullable
    private InterfaceBlockInfo findOrCreateProxyPort(@NotNull FindOrCreateProxyPortInfo findOrCreateProxyPortInfo) {
        LogUtil.printSerializeOnlineLogs("findOrCreateProxyPortInfo: ", findOrCreateProxyPortInfo);
        final Boolean isFindSourceConveyed = findOrCreateProxyPortInfo.getIsFindSourceConveyed();
        final ConveyedPermutationGroup conveyedPermutationGroup = findOrCreateProxyPortInfo.getConveyedPermutationGroup();
        final String projectId = findOrCreateProxyPortInfo.getProjectId();
        final MetaClassInstance partPropertyType = findOrCreateProxyPortInfo.getPartPropertyType();
        final List<InterfaceBlockInfo> interfaceBlockInfos = findOrCreateProxyPortInfo.getInterfaceBlockInfos();
        final List<AddModelDTO> addModelDTOS = findOrCreateProxyPortInfo.getAddModelDTOS();
        final Map<String, MetaClassInstance> interfaceBlockInstanceMap = findOrCreateProxyPortInfo.getInterfaceBlockInstanceMap();
        final List<UpdateModelDTO> updateModelDTOS = findOrCreateProxyPortInfo.getUpdateModelDTOS();
        final MetaClassInstance conveyed = BooleanUtils.isTrue(isFindSourceConveyed) ?
                conveyedPermutationGroup.getFirstNode() : conveyedPermutationGroup.getSecondNode();
        Boolean isBiDirectionTransmit = conveyedPermutationGroup.getIsBiDirectionTransmit();
        String endsLimitedDirection = conveyedPermutationGroup.getEndsLimitedDirection();
        if (Objects.isNull(conveyed)) {
            log.info("传输路径存在一端传递项为空");
            return null;
        }
        Set<String> limitedDirection = calculateLimitedDirection(isBiDirectionTransmit, isFindSourceConveyed, endsLimitedDirection);
        // 父类模块继承来的代理端口也符合查询条件
        List<MetaClassInstance> typeGeneralsCascade = internalUmlService.findGeneralsCascade(
                projectId, partPropertyType.getId(), true);
        // 如果物质必须inout双向传输，则接口模块下的流属性必须为inout才算匹配;如果不为inout传输,则只需要代理端口方向匹配即可
        InterfaceBlockInfo satisfiedInterfaceBlock = querySatisfiedInterfaceBlock(interfaceBlockInfos, conveyed, typeGeneralsCascade, limitedDirection);
        if (Objects.nonNull(satisfiedInterfaceBlock)) {
            satisfiedInterfaceBlock.appendAlreadyConveyed(conveyed);
            if (BooleanUtils.isTrue(isFindSourceConveyed)) {
                satisfiedInterfaceBlock.initSourceProxyPortInfo(partPropertyType, typeGeneralsCascade, limitedDirection);
            } else {
                satisfiedInterfaceBlock.initTargetProxyPortInfo(partPropertyType, typeGeneralsCascade, limitedDirection);
            }
            return satisfiedInterfaceBlock;
        }

        satisfiedInterfaceBlock = querySatisfiedInterfaceBlock(interfaceBlockInfos, conveyed, limitedDirection);
        if (Objects.isNull(satisfiedInterfaceBlock)) {
            log.error("传递项" + conveyed.getId() + "无符合条件的接口模块, interfaceBlockInfos初始化或填充失败");
            throw AbortExecutionException.build(ErrorCode.QUERY_MODEL_ERROR);
        }
        MetaClassInstance interfaceBlock = interfaceBlockInstanceMap.get(satisfiedInterfaceBlock.getInterfaceBlockId());
        // 新增代理端口
        AddModelDTO proxyPortDTO = createAddModelDTO(projectId, UMLDefinitionConstants.Port,
                partPropertyType.getId(), null, Collections.singletonList(UMLDefinitionConstants.SysML_ProxyPort));
        final String initProxyPortId = proxyPortDTO.getInstanceId();
        addModelDTOS.add(proxyPortDTO);
        final MetaClassInstance aggregation =
                internalUmlService.fetchInstance(UMLDefinitionConstants.AggregationKind_composite, projectId);
        updateModelDTOS.add(new UpdateModelDTO(projectId, initProxyPortId, UMLDefinitionConstants.Property_aggregation, aggregation));
        updateModelDTOS.add(new UpdateModelDTO(projectId, initProxyPortId, UMLDefinitionConstants.TypedElement_type, interfaceBlock));
        // 设置代理端口是否共轭
        String proxyPortDirection = satisfiedInterfaceBlock.getInterfaceBlockDirection();
        if (BooleanUtils.isFalse(compareDirection(proxyPortDirection, limitedDirection))) {
            updateModelDTOS.add(new UpdateModelDTO(projectId, initProxyPortId, UMLDefinitionConstants.Port_isConjugated, true));
            proxyPortDirection = Objects.equals(proxyPortDirection, UMLDefinitionConstants.SysML_FlowDirectionKind_out) ?
                    UMLDefinitionConstants.SysML_FlowDirectionKind_in : UMLDefinitionConstants.SysML_FlowDirectionKind_out;
        }
        // 代理端口信息存储至InterfaceBlockInfo
        ProxyPortInfo proxyPortInfo = new ProxyPortInfo(initProxyPortId, proxyPortDirection, partPropertyType);
        satisfiedInterfaceBlock.appendProxyPortInfo(proxyPortInfo);
        satisfiedInterfaceBlock.appendAlreadyConveyed(conveyed);
        if (BooleanUtils.isTrue(isFindSourceConveyed)) {
            satisfiedInterfaceBlock.initSourceProxyPortInfo(partPropertyType, typeGeneralsCascade, limitedDirection);
        } else {
            satisfiedInterfaceBlock.initTargetProxyPortInfo(partPropertyType, typeGeneralsCascade, limitedDirection);
        }
        return satisfiedInterfaceBlock;
    }

    /**
     * desciption:
     *
     * @param proxyPortDirection:当前的代理端口方向
     * @param limitedDirection:需要转化成的方向
     * @return java.lang.Boolean：true代表方向一致无需共轭，false代表需要共轭
     * @author lx
     * @date 2024/1/23
     */
    @NotNull
    private static Boolean compareDirection(String proxyPortDirection, Set<String> limitedDirection) {
        LogUtil.printOnlineLogs("proxyPortDirection: {}, limitedDirection: {}", proxyPortDirection, limitedDirection);
        if (limitedDirection.contains(UMLDefinitionConstants.SysML_FlowDirectionKind_out)
                && Objects.equals(proxyPortDirection, UMLDefinitionConstants.SysML_FlowDirectionKind_in)) {
            return false;
        }
        return !limitedDirection.contains(UMLDefinitionConstants.SysML_FlowDirectionKind_in)
                || !Objects.equals(proxyPortDirection, UMLDefinitionConstants.SysML_FlowDirectionKind_out);
    }

    @NotNull
    private List<InterfaceBlockInfo> initInterfaceBlockInfo(String projectId) {
        LogUtil.printOnlineLogs("initInterfaceBlockInfo -> projectId: ", projectId);
        List<MetaClassInstance> interfaceBlockList = internalUmlService.querySpecifiedInstanceList(projectId, UMLDefinitionConstants.SysML_InterfaceBlock);
        MofResultContainer interfaceBlockContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(interfaceBlockList,
                Stream.of(UMLDefinitionConstants.A_type_typedElement_typedElement,
                        UMLDefinitionConstants.Class_ownedAttribute).collect(Collectors.toList())));

        List<MetaClassInstance> proxyPortList = interfaceBlockList
                .stream()
                .flatMap(it -> interfaceBlockContainer.queryListInstanceProperty(it.getId(), UMLDefinitionConstants.A_type_typedElement_typedElement).stream())
                .filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.SysML_ProxyPort))
                .collect(Collectors.toList());

        List<MetaClassInstance> flowPropertyList = interfaceBlockList
                .stream()
                .flatMap(it -> interfaceBlockContainer.queryListInstanceProperty(it.getId(), UMLDefinitionConstants.Class_ownedAttribute).stream())
                .filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.SysML_FlowProperty))
                .collect(Collectors.toList());

        MofResultContainer proxyPortContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(proxyPortList,
                Stream.of(UMLDefinitionConstants.Element_owner,
                        UMLDefinitionConstants.Port_isConjugated).collect(Collectors.toList())));

        MofResultContainer flowPropertyContainer = internalUmlService.queryProperty(
                projectId, internalUmlService.getQueryPropertyForm(flowPropertyList,
                        Stream.of(UMLDefinitionConstants.TypedElement_type,
                                UMLDefinitionConstants.SysML_FlowProperty_direction).collect(Collectors.toList())));
        return interfaceBlockList.stream().map(interfaceBlock -> {
            String interfaceBlockId = interfaceBlock.getId();
            InterfaceBlockInfo interfaceBlockInfo = new InterfaceBlockInfo();

            // 计算应用该接口模块的方向
            List<MetaClassInstance> tempFlowPropertyList = interfaceBlockContainer
                    .queryListInstanceProperty(interfaceBlockId, UMLDefinitionConstants.Class_ownedAttribute)
                    .stream().filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.SysML_FlowProperty))
                    .collect(Collectors.toList());

            List<PropertyInfo> propertyInfoList = tempFlowPropertyList.stream().map(tempFlowProperty -> {
                MetaClassInstance propertyType = flowPropertyContainer.queryInstanceProperty(
                        tempFlowProperty.getId(), UMLDefinitionConstants.TypedElement_type);
                Set<String> flowPropertyDirection = flowPropertyContainer.queryListInstanceProperty(
                        tempFlowProperty.getId(), UMLDefinitionConstants.SysML_FlowProperty_direction)
                        .stream().map(BasicRElement::getId).collect(Collectors.toSet());
                return new PropertyInfo(propertyType, flowPropertyDirection);
            }).collect(Collectors.toList());

            Set<String> tempFlowPropertyDirectionSet = tempFlowPropertyList.stream().flatMap(it ->
                    flowPropertyContainer.queryListInstanceProperty(it.getId(), UMLDefinitionConstants.SysML_FlowProperty_direction).stream())
                    .filter(Objects::nonNull)
                    .map(BasicRElement::getId)
                    .collect(Collectors.toSet());

            String flowPropertyDirection = calculateFlowPropertyDirection(tempFlowPropertyDirectionSet);
            Set<MetaClassInstance> tempFlowPropertyTypeSet = tempFlowPropertyList.stream().map(it ->
                    flowPropertyContainer.queryInstanceProperty(it.getId(), UMLDefinitionConstants.TypedElement_type))
                    .collect(Collectors.toSet());

            List<MetaClassInstance> tempProxyPortList = interfaceBlockContainer.queryListInstanceProperty(
                    interfaceBlockId, UMLDefinitionConstants.A_type_typedElement_typedElement)
                    .stream().filter(it ->
                            internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.SysML_ProxyPort))
                    .collect(Collectors.toList());
            List<ProxyPortInfo> proxyPortInfoList = tempProxyPortList.stream().map(tempProxyPort -> {
                MetaClassInstance owner = proxyPortContainer.queryInstanceProperty(tempProxyPort.getId(), UMLDefinitionConstants.Element_owner);
                Boolean portIsConjugated = proxyPortContainer.queryBooleanProperty(tempProxyPort.getId(), UMLDefinitionConstants.Port_isConjugated);
                // 不能直接通过查询得到代理端口显示的方向，其结果为代理端口的方向 + 是否共轭计算得来
                String proxyPortDirection = calculateProxyPortDirection(flowPropertyDirection, portIsConjugated);
                return new ProxyPortInfo(tempProxyPort.getId(), proxyPortDirection, owner);
            }).collect(Collectors.toList());

            interfaceBlockInfo.setInterfaceBlockId(interfaceBlockId);
            interfaceBlockInfo.setInterfaceBlockDirection(flowPropertyDirection);
            interfaceBlockInfo.setCanConveyedSet(tempFlowPropertyTypeSet);
            interfaceBlockInfo.setPropertyInfoList(propertyInfoList);
            interfaceBlockInfo.setProxyPortInfoList(proxyPortInfoList);
            return interfaceBlockInfo;
        }).collect(Collectors.toList());
    }

    private void createAndFillInterfaceBlockInfo(String projectId,
                                                 List<InterfaceBlockInfo> interfaceBlockInfos,
                                                 List<ItemFlowGroup> itemFlowGroupList,
                                                 MetaClassInstance nearestPackage) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, interfaceBlockInfos: {}, itemFlowGroupList: {}, nearestPackage: {}",
                projectId, interfaceBlockInfos, itemFlowGroupList, nearestPackage);
        List<AddModelDTO> addInterfaceBlockDTOS = new ArrayList<>();
        List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
        Map<MetaClassInstance, Set<Object>> conveyedTransmitMap = initConveyedTransmitMap(itemFlowGroupList);
        if (MapUtils.isEmpty(conveyedTransmitMap)) {
            log.error("活动图中节点间均不存在物质传输");
            throw AbortExecutionException.build(ErrorCode.CREATE_IBD_NO_COMMUNICATION_ERROR);
        }
        Map<String, MetaClassInstance> flowDirectionMap = internalUmlService.fetchInstances(
                Stream.of(UMLDefinitionConstants.SysML_FlowDirectionKind_out,
                        UMLDefinitionConstants.SysML_FlowDirectionKind_inout).collect(Collectors.toList()),
                projectId);
        MofResultContainer conveyedContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(
                new ArrayList<>(conveyedTransmitMap.keySet()),
                Stream.of(UMLDefinitionConstants.NamedElement_name).collect(Collectors.toList())));

        conveyedTransmitMap.keySet().forEach(conveyed -> {
            Set<Object> isBiDirectionTransmitSet = conveyedTransmitMap.get(conveyed);
            InterfaceBlockInfo satisfiedInfo;
            MetaClassInstance flowPropertyDirection;
            // 1.如果物质为双向传输,则找inout的流属性 2.如果传输物质包含in方向,则找in的流属性
            if (isBiDirectionTransmitSet.contains(true)) {
                satisfiedInfo = querySatisfiedInterfaceBlock(
                        interfaceBlockInfos, conveyed, Collections.singleton(UMLDefinitionConstants.SysML_FlowDirectionKind_inout));
                flowPropertyDirection = flowDirectionMap.get(UMLDefinitionConstants.SysML_FlowDirectionKind_inout);
            } else {
                satisfiedInfo = interfaceBlockInfos.stream().filter(it -> it.getCanConveyedSet().contains(conveyed)).findFirst().orElse(null);
                flowPropertyDirection = flowDirectionMap.get(UMLDefinitionConstants.SysML_FlowDirectionKind_out);
            }
            // 如果找不到符合条件的接口模块 或 非用户创建的传递项类型，则创建新的接口模块及属性
            boolean createInterfaceBlockFlag = Objects.isNull(satisfiedInfo) ||
                    !BusinessJudgeService.isCreatedInteractive(conveyed);
            if (createInterfaceBlockFlag) {
                String conveyedName = conveyedContainer.queryStringProperty(conveyed.getId(), UMLDefinitionConstants.NamedElement_name);
                String interfaceBlockDefaultName = Objects.isNull(conveyedName) ? "i" : "i" + conveyedName;
                AddModelDTO interfaceBlockDTO = createAddModelDTO(projectId, UMLDefinitionConstants.Class,
                        nearestPackage.getId(), interfaceBlockDefaultName, Collections.singletonList(UMLDefinitionConstants.SysML_InterfaceBlock));
                String initInterfaceBlockId = interfaceBlockDTO.getInstanceId();

                List<String> stereoTypes = BusinessJudgeService.isCreatedInteractive(conveyed) ?
                        Collections.singletonList(UMLDefinitionConstants.SysML_FlowProperty) : new ArrayList<>();

                AddModelDTO propertyDTO = createAddModelDTO(
                        projectId, UMLDefinitionConstants.Property, initInterfaceBlockId, null, stereoTypes);

                updateModelDTOS.add(new UpdateModelDTO(projectId, propertyDTO.getInstanceId(), UMLDefinitionConstants.TypedElement_type, conveyed));
                updateModelDTOS.add(new UpdateModelDTO(projectId, propertyDTO.getInstanceId(), UMLDefinitionConstants.SysML_FlowProperty_direction, flowPropertyDirection));
                addInterfaceBlockDTOS.addAll(Stream.of(interfaceBlockDTO, propertyDTO).collect(Collectors.toList()));

                satisfiedInfo = new InterfaceBlockInfo();
                satisfiedInfo.setInterfaceBlockId(initInterfaceBlockId);
                satisfiedInfo.appendPropertyInfo(new PropertyInfo(conveyed, Collections.singleton(flowPropertyDirection.getId())));
                satisfiedInfo.setCanConveyedSet(Collections.singleton(conveyed));
                satisfiedInfo.setInterfaceBlockDirection(flowPropertyDirection.getId());
                interfaceBlockInfos.add(satisfiedInfo);
            }
        });
        // 一定得先批量生成接口模块，否则代理端口的类型无法设置为接口模块
        if (CollectionUtils.isNotEmpty(addInterfaceBlockDTOS)) {
            umlService.addModel(addInterfaceBlockDTOS);
        }
        if (CollectionUtils.isNotEmpty(updateModelDTOS)) {
            umlService.updateModelByBatch(updateModelDTOS);
        }
        // 逆置列表保证每次查找得到的接口模块是最新添加的
        Collections.reverse(interfaceBlockInfos);
    }

    /**
     * desciption:
     */
    @NotNull
    private static Map<MetaClassInstance, Set<Object>> initConveyedTransmitMap(List<ItemFlowGroup> itemFlowGroupList) {
        LogUtil.printSerializeOnlineLogs("itemFlowGroupList: ", itemFlowGroupList);
        Map<MetaClassInstance, Set<Object>> conveyedTransmitMap = new HashMap<>();
        itemFlowGroupList.forEach(itemFlowGroup -> {
            List<ConveyedPermutationGroup> conveyedPermutationGroups = itemFlowGroup.getConveyedPermutationGroups();
            conveyedPermutationGroups.forEach(conveyedPermutationGroup -> {
                MetaClassInstance firstNode = conveyedPermutationGroup.getFirstNode();
                MetaClassInstance secondNode = conveyedPermutationGroup.getSecondNode();
                Boolean isBiDirectionTransmit = conveyedPermutationGroup.getIsBiDirectionTransmit();
                if (Objects.nonNull(firstNode)) {
                    appendMapValue(conveyedTransmitMap, firstNode, isBiDirectionTransmit);
                }
                if (Objects.nonNull(secondNode)) {
                    appendMapValue(conveyedTransmitMap, secondNode, isBiDirectionTransmit);
                }
            });
        });
        return conveyedTransmitMap;
    }

    @NotNull
    private static AddModelDTO createAddModelDTO(String projectId,
                                                 String metaClass,
                                                 String parentId,
                                                 String defaultName,
                                                 List<String> applyStereotypes) {
        LogUtil.printOnlineLogs("projectId: {}, metaClass: {}, parentId: {}, defaultName: {}, applyStereotypes: {}",
                projectId, metaClass, parentId, defaultName, applyStereotypes);
        final String initModelId = ModelConstantURI.initInstanceId();
        AddModelDTO addModelDTO = new AddModelDTO();
        addModelDTO.setProjectId(projectId);
        addModelDTO.setType(0);
        addModelDTO.setMetaclass(metaClass);
        addModelDTO.setParentId(parentId);
        addModelDTO.setDefaultName(defaultName);
        addModelDTO.setApplyStereotypes(applyStereotypes);
        addModelDTO.setInstanceId(initModelId);
        return addModelDTO;
    }

    private static void appendMapValue(Map<MetaClassInstance, Set<Object>> allConveyedMap, MetaClassInstance key, Object value) {
        LogUtil.printSerializeOnlineLogs("key: {}, value: {}", key, value);
        Set<Object> isBiDirectionTransmit = allConveyedMap.containsKey(key) ? allConveyedMap.get(key) : new HashSet<>();
        isBiDirectionTransmit.add(value);
        allConveyedMap.put(key, isBiDirectionTransmit);
    }

    @Nullable
    private static String calculateFlowPropertyDirection(Set<String> tempFlowPropertyDirectionSet) {
        LogUtil.printSerializeOnlineLogs("tempFlowPropertyDirectionSet: ", tempFlowPropertyDirectionSet);
        String flowPropertyDirection;
        if (tempFlowPropertyDirectionSet.size() > 1) {
            flowPropertyDirection = UMLDefinitionConstants.SysML_FlowDirectionKind_inout;
        } else if (tempFlowPropertyDirectionSet.size() == 1) {
            flowPropertyDirection = tempFlowPropertyDirectionSet.iterator().next();
        } else {
            flowPropertyDirection = null;
        }
        return flowPropertyDirection;
    }

    @Nullable
    private static String calculateProxyPortDirection(String flowPropertyDirection, Boolean isConjugated) {
        LogUtil.printOnlineLogs("flowPropertyDirection: {}, isConjugated: {}", flowPropertyDirection, isConjugated);
        if (BooleanUtils.isFalse(isConjugated)) {
            return flowPropertyDirection;
        }
        if (StringUtils.equals(flowPropertyDirection, UMLDefinitionConstants.SysML_FlowDirectionKind_in)) {
            return UMLDefinitionConstants.SysML_FlowDirectionKind_out;
        } else if (StringUtils.equals(flowPropertyDirection, UMLDefinitionConstants.SysML_FlowDirectionKind_out)) {
            return UMLDefinitionConstants.SysML_FlowDirectionKind_in;
        } else {
            return flowPropertyDirection;
        }
    }

    @Getter
    static class ConnectorPo {

        private final ConnectorGroup connectorGroup;

        private List<MetaClassInstance> connectorEnd;

        private List<MetaClassInstance> connectors;

        public ConnectorPo(ConnectorGroup connectorGroup) {
            this.connectorGroup = connectorGroup;
        }

        public void init(MofResultContainer mofResultContainer) {
            this.connectorEnd = mofResultContainer.queryListInstanceProperty(connectorGroup.getConnectorSource(),
                    UMLDefinitionConstants.ConnectableElement_end);
            this.connectors = connectorEnd.stream().map(end -> mofResultContainer.queryInstanceProperty(end.getId(),
                    UMLDefinitionConstants.A_end_connector_connector)).collect(Collectors.toList());
        }

        @Nullable
        public MetaClassInstance getConnector(MofResultContainer mofResultContainer) {
            Optional<MetaClassInstance> result = this.connectors.stream().filter(connector -> {
                List<MetaClassInstance> ends = mofResultContainer.queryListInstanceProperty(connector.getId(),
                        UMLDefinitionConstants.Connector_end);
                if (ends.size() != 2) {
                    return false;
                }

                MetaClassInstance sourceEnd = ends.get(0);
                MetaClassInstance targetEnd = ends.get(1);
                List<MetaClassInstance> sourceEnds =
                        mofResultContainer.queryListInstanceProperty(connectorGroup.getConnectorSource(),
                                UMLDefinitionConstants.ConnectableElement_end);
                if (sourceEnds.stream().noneMatch(it -> it.getId().equals(sourceEnd.getId()))) {
                    return false;
                }

                List<MetaClassInstance> targetEnds =
                        mofResultContainer.queryListInstanceProperty(connectorGroup.getConnectorTarget(),
                                UMLDefinitionConstants.ConnectableElement_end);
                if (targetEnds.stream().noneMatch(it -> it.getId().equals(targetEnd.getId()))) {
                    return false;
                }

                MetaClassInstance sourcePart = mofResultContainer.queryInstanceProperty(sourceEnd.getId(),
                        UMLDefinitionConstants.ConnectorEnd_partWithPort);
                MetaClassInstance targetPart = mofResultContainer.queryInstanceProperty(targetEnd.getId(),
                        UMLDefinitionConstants.ConnectorEnd_partWithPort);
                if (!isValidPartWithPort(sourcePart, connectorGroup.getSourcePartProperty())) {
                    return false;
                }

                return isValidPartWithPort(targetPart, connectorGroup.getTargetPartProperty());
            }).findFirst();
            return result.orElse(null);
        }

        private static boolean isValidPartWithPort(MetaClassInstance part, String partPropertyId) {
            if (part == null) {
                return true;
            }

            if (partPropertyId == null) {
                return true;
            }

            return Objects.equals(part.getId(), partPropertyId);
        }
    }

    /**
     * desciption:填充ConnectorGroup的connector属性
     */
    private void fillGroupConnector(String projectId, String blockId, IbdDisplayModel ibdDisplayModel) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, blockId: {}, ibdDisplayModel: {}", projectId, blockId,
                ibdDisplayModel);
        // 1.查询ConnectorGroup的connectorSource代理端口与connectorTarget代理端口是否存在连接器:存在则直接填充;不存在则创建连接器
        List<ConnectorGroup> groups = ibdDisplayModel.getConnectorGroupList();
        //查询已存在的和source端相关的connector
        MofResultContainer mofResultContainer = queryGroupConnectorContainer(projectId, groups);
        //创建connector,并填充
        List<ConnectorPo> pos = createAndFillConnector(projectId, blockId, groups, mofResultContainer);
        // 2.ConnectorGroup的ItemFlowSet的项流实现连接器属性添加connector:
        appendRealizingConnector(projectId, pos);
    }

    @NotNull
    private MofResultContainer queryGroupConnectorContainer(String projectId, List<ConnectorGroup> connectorGroupList) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, connectorGroupList: {}", projectId, connectorGroupList);
        List<String> sourceIds = connectorGroupList.stream().map(ConnectorGroup::getConnectorSource)
                .collect(Collectors.toList());
        List<String> targetIds = connectorGroupList.stream().map(ConnectorGroup::getConnectorTarget)
                .collect(Collectors.toList());
        List<MetaClassInstance> roles =
                internalUmlService.fetchInstanceByIds(Stream.concat(sourceIds.stream(), targetIds.stream())
                                .collect(Collectors.toList()),
                        projectId);
        QueryPropertyForm form = internalUmlService.getQueryPropertyForm(roles,
                Stream.of(UMLDefinitionConstants.ConnectableElement_end).collect(Collectors.toList()));
        MofResultContainer mofResultContainer = internalUmlService.queryProperty(projectId, form);

        // 代理端口 -> 连接器端
        List<MetaClassInstance> sourceEnds =
                sourceIds.stream().flatMap(it -> mofResultContainer.queryListInstanceProperty(it,
                        UMLDefinitionConstants.ConnectableElement_end).stream())
                        .collect(Collectors.toList());
        List<MetaClassInstance> targetEnds =
                targetIds.stream().flatMap(it -> mofResultContainer.queryListInstanceProperty(it,
                        UMLDefinitionConstants.ConnectableElement_end).stream())
                        .collect(Collectors.toList());

        QueryPropertyForm form1 = internalUmlService.getQueryPropertyForm(Stream.concat(sourceEnds.stream(), targetEnds.stream())
                .collect(Collectors.toList()), Stream.of(UMLDefinitionConstants.A_end_connector_connector,
                UMLDefinitionConstants.ConnectorEnd_partWithPort).collect(Collectors.toList()));
        mofResultContainer.addMofPropertyResult(internalUmlService.queryProperty(projectId, form1));
        List<MetaClassInstance> connectors =
                sourceEnds.stream().map(it -> mofResultContainer.queryInstanceProperty(it.getId(),
                        UMLDefinitionConstants.A_end_connector_connector))
                        .collect(Collectors.toList());
        mofResultContainer.addMofPropertyResult(internalUmlService.queryProperty(projectId,
                internalUmlService.getQueryPropertyForm(connectors,
                        Stream.of(UMLDefinitionConstants.Connector_end).collect(Collectors.toList()))));
        return mofResultContainer;
    }

    private void appendRealizingConnector(String projectId, List<ConnectorPo> pos) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, pos: {}", projectId, pos);
        CreateModelDto appendRealizingConnector = new CreateModelDto(projectId);
        Map<String, MetaClassInstance> connectorMap =
                internalUmlService.fetchInstances(pos.stream().map(it -> it.getConnectorGroup().getConnector()).collect(Collectors.toList()), projectId);
        MofResultContainer connectorContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(
                new ArrayList<>(connectorMap.values()),
                Stream.of(UMLDefinitionConstants.A_realizingConnector_informationFlow_informationFlow).collect(Collectors.toList())));

        pos.forEach(po -> {
            final MetaClassInstance newConnector = connectorMap.get(po.getConnectorGroup().getConnector());
            if (newConnector == null) {
                return;
            }
            List<String> connectorItemFlowIds = connectorContainer.queryListInstanceProperty(
                    newConnector.getId(), UMLDefinitionConstants.A_realizingConnector_informationFlow_informationFlow)
                    .stream().map(BasicRElement::getId).collect(Collectors.toList());
            po.connectorGroup.getItemFlowIdSet().forEach(itemFlowId -> {
                if (!connectorItemFlowIds.contains(itemFlowId)) {
                    appendRealizingConnector.addAppendModelValueDTO(projectId, itemFlowId,
                            UMLDefinitionConstants.InformationFlow_realizingConnector,
                            Stream.of(newConnector).collect(Collectors.toList()));
                }
            });
        });
        umlService.executeCreateModelDTO(appendRealizingConnector);
    }

    @NotNull
    private List<ConnectorPo> createAndFillConnector(String projectId,
                                                     String blockId,
                                                     List<ConnectorGroup> connectorGroupList,
                                                     MofResultContainer mofResultContainer) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, blockId: {}, connectorGroupList: {}", projectId, blockId,
                connectorGroupList);
        List<CreateModelDto> createModelDtos = new ArrayList<>();
        List<ConnectorPo> pos = new ArrayList<>();
        connectorGroupList.forEach(group -> {
            ConnectorPo po = new ConnectorPo(group);
            po.init(mofResultContainer);
            pos.add(po);
            MetaClassInstance connector = po.getConnector(mofResultContainer);
            String newConnectorId;
            if (connector != null) {
                newConnectorId = connector.getId();
            } else {
                newConnectorId = ModelConstantURI.initInstanceId();
                group.setConnector(newConnectorId);
                AddConnectorDto addConnectDTO = new AddConnectorDto();
                addConnectDTO.setType(CommandAddType.RELATIONSHIP.getCode());
                addConnectDTO.setMetaclass(UMLDefinitionConstants.Connector);
                addConnectDTO.setInstanceId(newConnectorId);
                addConnectDTO.setSource(po.connectorGroup.getConnectorSource());
                addConnectDTO.setTarget(po.connectorGroup.getConnectorTarget());
                addConnectDTO.setProjectId(projectId);
                addConnectDTO.setParentId(blockId);
                addConnectDTO.setApplyStereotypes(new ArrayList<>());
                addConnectDTO.setSourceLocation(po.connectorGroup.getSourcePartProperty());
                addConnectDTO.setTargetLocation(po.connectorGroup.getTargetPartProperty());
                createModelDtos.add(createConnector.makeCreateModelDTO(addConnectDTO));
            }

            group.setConnector(newConnectorId);

        });
        umlService.executeCreateModelDTO(createModelDtos);
        return pos;
    }

}
